package cn.lili.modules.wallet.serviceimpl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
import cn.lili.modules.order.trade.entity.dto.RechargeQueryParams;
import cn.lili.modules.order.trade.entity.vo.RechargeQueryVO;
import cn.lili.modules.payment.entity.dos.PaymentLog;
import cn.lili.modules.payment.entity.dos.Recharge;
import cn.lili.modules.payment.entity.dto.PaymentCallback;
import cn.lili.modules.payment.entity.dto.UserWalletUpdateDTO;
import cn.lili.modules.payment.entity.enums.PlatformWalletEnum;
import cn.lili.modules.payment.entity.enums.WalletServiceTypeEnum;
import cn.lili.modules.wallet.mapper.RechargeMapper;
import cn.lili.modules.wallet.service.RechargeService;
import cn.lili.modules.wallet.service.WalletService;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 预存款业务层实现
 *
 * @author pikachu
 * @since 2020-02-25 14:10:16
 */
@Service
@RequiredArgsConstructor
public class RechargeServiceImpl extends ServiceImpl<RechargeMapper, Recharge> implements RechargeService {

    /**
     * 用户钱包
     */
    private final WalletService walletService;

    @Override
    @Transactional
    public Recharge recharge(Double price) {
        if (price < 0.1) {
            throw new ServiceException("充值金额单次最少充值金额为0.1元");
        }
        //获取当前登录的会员
        AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
        //构建sn
        String sn = "Y" + SnowFlake.getId();
        //整合充值订单数据
        Recharge recharge = new Recharge(sn, UserContext.getCurrentId(), authUser.getUsername(), price);
        //添加预存款充值账单
        this.save(recharge);
        //返回预存款
        return recharge;
    }

    @Override
    public Page<Recharge> rechargePage(PageVO page, RechargeQueryVO rechargeQueryVO) {
        //构建查询条件
        QueryWrapper<Recharge> queryWrapper = new QueryWrapper<>();
        //会员名称
        queryWrapper.like(!CharSequenceUtil.isEmpty(rechargeQueryVO.getNickName()), "nick_name", rechargeQueryVO.getNickName());
        //充值订单号
        queryWrapper.eq(!CharSequenceUtil.isEmpty(rechargeQueryVO.getRechargeSn()), "recharge_sn", rechargeQueryVO.getRechargeSn());
        //会员id
        queryWrapper.eq(!CharSequenceUtil.isEmpty(rechargeQueryVO.getUserId()), "user_id", rechargeQueryVO.getUserId());
        //支付时间 开始时间和结束时间
        if (!CharSequenceUtil.isEmpty(rechargeQueryVO.getStartDate()) && !CharSequenceUtil.isEmpty(rechargeQueryVO.getEndDate())) {
            Date start = cn.hutool.core.date.DateUtil.parse(rechargeQueryVO.getStartDate());
            Date end = cn.hutool.core.date.DateUtil.parse(rechargeQueryVO.getEndDate());
            queryWrapper.between("pay_time", start, end);
        }
        queryWrapper.orderByDesc("create_time");
        //查询返回数据
        return this.page(PageUtil.initPage(page), queryWrapper);
    }

    /**
     * 查询充值订单列表
     *
     * @param queryParams 查询条件
     * @return 充值订单列表
     */
    @Override
    public List<Recharge> list(RechargeQueryParams queryParams) {
        return this.list(queryParams.queryWrapper());
    }

    @Override
    @Transactional
    public void paySuccess(PaymentCallback paymentCallback) {

        log.debug("余额充值到达回调0");

        //获取支付日志
        PaymentLog paymentLog = paymentCallback.getPaymentLog();
        if (paymentLog == null) {
            throw new ServiceException(ResultCode.PAY_NOT_EXIST_ORDER);
        }
        //根据sn获取支付账单
        Recharge recharge = this.getOne(new QueryWrapper<Recharge>().eq("recharge_sn", paymentLog.getOrderSn()));

        log.debug("余额充值到达回调1");

        //如果支付账单不为空则进行一下逻辑
        if (recharge != null && !recharge.getPayStatus().equals(PayStatusEnum.PAID.name())) {
            //将此账单支付状态更改为已支付
            recharge.setPayStatus(PayStatusEnum.PAID.name());
            recharge.setReceivableNo(paymentLog.getTransactionId());
            recharge.setPayTime(new DateTime());
            recharge.setRechargeWay(paymentLog.getPaymentMethod());
            //执行保存操作
            this.updateById(recharge);

            log.debug("余额充值到达回调2");

            //增加预存款余额
            walletService.recharge(
                    UserWalletUpdateDTO.builder()
                            .amount(recharge.getRechargeMoney())
                            .userId(recharge.getUserId())
                            .detail(UserWalletUpdateDTO.generateRechargeDescription(recharge.getRechargeSn()))
                            .serviceType(WalletServiceTypeEnum.RECHARGE)
                            .transactionId(paymentLog.getTransactionId())
                            .outTradeNo(paymentLog.getOutTradeNo())
                            .platformWalletId(
                                    paymentCallback.isThirdPayment() ? PlatformWalletEnum.THIRD_PAYMENT.getWalletUserId() :
                                            PlatformWalletEnum.OFFLINE.getWalletUserId())
                            .build());

        }


    }

    @Override
    public Recharge getRechargeBySn(String sn) {
        Recharge recharge = this.getOne(new QueryWrapper<Recharge>().eq("recharge_sn", sn));
        if (recharge != null) {
            return recharge;
        }
        throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
    }


    @Override
    @Transactional
    public void cancel(String sn) {
        Recharge recharge = this.getOne(new QueryWrapper<Recharge>().eq("recharge_sn", sn));
        if (recharge != null) {
            recharge.setPayStatus(PayStatusEnum.CANCEL.name());
            this.updateById(recharge);
        }
    }


    @Override
    public void autoCancel() {
        //充值订单自动取消时间 = 当前时间 - 自动取消时间分钟数
        DateTime cancelTime = DateUtil.offsetMinute(DateUtil.date(), -30);
        RechargeQueryParams queryParams = new RechargeQueryParams();
        queryParams.setPayStatus(PayStatusEnum.UNPAID.name());
        queryParams.setLeCreateTime(cancelTime);
        List<Recharge> list = this.list(queryParams);
        if (CollUtil.isNotEmpty(list)) {
            List<String> cancelSnList = list.stream().map(Recharge::getRechargeSn).collect(Collectors.toList());
            for (String sn : cancelSnList) {
                this.cancel(sn);
            }
        }
    }
}